﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Kaleta.Xna.Timing
{
    public interface IEffects
    {
        void Add(VisualEffect effect);
        void Update(GameTime gameTime);
        void Draw();
    }

    /// <summary>
    /// This is the effect container, in which all effects resides. Updating and drawing the container does the same to all effects.
    /// </summary>
    public class Effects : IEffects
    {
        private List<VisualEffect> Container = new List<VisualEffect>();
        private List<VisualEffect> RemovalContainer = new List<VisualEffect>();

        public void Add(VisualEffect effect)
        {
            Container.Add(effect);
            effect.Finished += new EventHandler(effect_Finished);
        }

        void effect_Finished(object sender, EventArgs e)
        {
            RemovalContainer.Add((VisualEffect)sender);
        }

        public void Update(GameTime gameTime)
        {
            foreach (var effect in Container)
                effect.Update(gameTime);

            if (RemovalContainer.Any())
            {
                Container.RemoveAll(effect => RemovalContainer.Contains(effect));
                RemovalContainer.Clear();
            }
        }

        public void Draw()
        {
            foreach (var effect in Container)
            {
                effect.Draw();
            }
        }
    }

    /// <summary>
    /// This type handles timeline visual effect. 
    /// </summary>
    public abstract class VisualEffect 
    {
        protected Storyboard Storyboard = new Storyboard();
        

        public event EventHandler Finished;

        public VisualEffect()
        {
            Storyboard.Finished += new EventHandler(Storyboard_Finished);

            Effects.Add(this);
        }

        /// <summary>
        /// Override this method to create additional behavior for this visual effect.
        /// </summary>
        /// <param name="gameTime"></param>
        public virtual void Update(GameTime gameTime)
        {
            Storyboard.Update(gameTime);
        }

        /// <summary>
        /// Draws the effect.
        /// </summary>
        public abstract void Draw();

        void Storyboard_Finished(object sender, EventArgs e)
        {
            if (Finished != null)
                Finished(this, null);
        }

        /// <summary>
        /// Defines the effect container. This container will handle Update/Draw for each effect in it.
        /// </summary>
        /// <param name="effects"></param>
        static public void SetEffectsContainer(IEffects container)
        {
            Effects = container;
        }

        static private IEffects Effects;
    }

}
